package com.education.platform.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.education.platform.api.config.ThreadUser;
import com.education.platform.api.constants.RedisCacheConstant;
import com.education.platform.api.service.*;
import com.education.platform.api.service.common.CacheDataService;
import com.education.platform.api.service.entity.*;
import com.education.platform.api.vo.request.LoginCompleteRequestVO;
import com.education.platform.api.vo.request.LoginThirdPartyRequestVO;
import com.education.platform.common.encrypt.MD5Util;
import com.education.platform.common.enums.MemberTypeEnum;
import com.education.platform.common.enums.SmsTypeEnum;
import com.education.platform.common.exception.AssertException;
import com.education.platform.common.exception.BusinessException;
import com.education.platform.common.redis.RedisUtils;
import com.education.platform.api.service.common.Validservice;
import com.education.platform.common.util.BeanUtil;
import com.education.platform.common.util.ShareCodeUtil;
import com.education.platform.common.util.StringUtils;
import com.education.platform.common.util.UUIDGenerator;
import com.education.platform.dao.ReceiptAddressDao;
import com.education.platform.dao.UserCountDao;
import com.education.platform.dao.entity.*;
import com.education.platform.dao.model.PointsRankModel;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 *
 * @Description : 登陆
 */
@Service
public class LoginServiceImpl implements LoginService {

    private Logger logger = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Value("${token.expire}")
    private int tokenExpire;

    @Autowired
    private UserBaseService userBaseService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private UserPointsService userPointsService;

    @Autowired
    private Validservice validservice;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private CacheDataService cacheDataService;

    @Autowired
    private UserOrderService userOrderService;
    @Autowired
    private UserAuthService userAuthService;

    @Autowired
    private ReceiptAddressDao receiptAddressDao;
    @Autowired
    private UserCountService userCountService;

    @Autowired
    private UserCountDao userCountDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginSuccessDTO login(String phone,String code) {
        //校验验证码是否正确
        validservice.validMessageCodeThrowE(phone,code, SmsTypeEnum.LOGIN_CODE.getValue());
        //获取用户信息，没有则创建用户
        UserBaseDO user = userCheck(phone);
        //token生成
        String token = createToken();
       //保存登录信息到redis缓存
        saveLoginCache( token, JSON.toJSONString(user));
        LoginSuccessDTO result = buildLoginSuccess( user,token);
        return result;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginSuccessDTO login(Integer userId) {
        UserBaseDO user = userBaseService.getById(userId);
        //token生成
        String token = createToken();
        //保存登录信息到redis缓存
        saveLoginCache( token, JSON.toJSONString(user));
        LoginSuccessDTO result = buildLoginSuccess( user,token);
        return result;
    }

    /**
     * 第三方认证绑定登录
     *
     * @param loginRequestVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginSuccessDTO login(LoginThirdPartyRequestVO loginRequestVO) {
        //校验验证码是否正确
        validservice.validMessageCodeThrowE(loginRequestVO.getPhone(),loginRequestVO.getVerificationCode(), SmsTypeEnum.LOGIN_CODE.getValue());
        //获取用户信息，没有则创建用户(如果第三方登录绑定的手机号 已经用手机号创建过账号，则直接合并账号)
        UserBaseDO user = userCheck(loginRequestVO);
        //创建userAuth，关联
        UserAuthDO userAuthDO = new UserAuthDO();
        userAuthDO.setUserId(user.getId());
        userAuthDO.setThirdType(loginRequestVO.getThirdType());
        userAuthDO.setThirdKey(loginRequestVO.getThirdKey());
        userAuthDO.setCreateTime(new Date());
        if(!userAuthService.insert(userAuthDO)){
            AssertException.throwBusinessEp("登录异常！");
        }
        //token生成
        String token = createToken();
        //保存登录信息到redis缓存
        saveLoginCache( token, JSON.toJSONString(user));
        LoginSuccessDTO result = buildLoginSuccess( user,token);
        return result;
    }

    /**
     * 退出登录
     *
     * @return
     */
    @Override
    public void logout() {
      String tokenRedisKey =  ThreadUser.getUserTokenRedisKey();
      if(StringUtils.isEmpty(tokenRedisKey)){
          AssertException.throwBusinessEp("当前未登录！");
      }else{
          redisUtils.del(tokenRedisKey);
      }
    }

    /**
     * 完善注册登录
     * @param
     * @param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginSuccessDTO complete(LoginCompleteRequestVO completeRequestVO) {
        UserBaseDO userBaseDTO = ThreadUser.getUser(UserBaseDO.class);
        //完善选择的年级
        UserBaseDO updateUser  = new UserBaseDO();
        updateUser.setId(userBaseDTO.getId());
        updateUser.setGrade(completeRequestVO.getGrade());
        updateUser.setGradeName(completeRequestVO.getGradeName());
        updateUser.setProvince(completeRequestVO.getProvince());
        updateUser.setCity(completeRequestVO.getCity());
        updateUser.setCounty(completeRequestVO.getCounty());
        updateUser.setUpdateTime(new Date());
        if(!userBaseService.updateById(updateUser)){
            throw new BusinessException("完善信息失败");
        }
        userBaseDTO.setGrade(completeRequestVO.getGrade());
        userBaseDTO.setGradeName(completeRequestVO.getGradeName());
        userBaseDTO.setProvince(completeRequestVO.getProvince());
        userBaseDTO.setCity(completeRequestVO.getCity());
        userBaseDTO.setCounty(completeRequestVO.getCounty());
        userBaseDTO.setUpdateTime(new Date());
        //重新保存
        redisUtils.setString(ThreadUser.getUserTokenRedisKey(),tokenExpire,JSON.toJSONString(userBaseDTO));
        LoginSuccessDTO result = buildLoginSuccess( userBaseDTO);
        return result;
    }

    /**
     * 根据手机号查找用户，没有则创建用户
     * @param
     * @return
     */
    private UserBaseDO userCheck(LoginThirdPartyRequestVO loginRequestVO) {
        UserBaseDO baseDTO = new UserBaseDO();
        baseDTO.setPhone(loginRequestVO.getPhone());
        baseDTO.setDeleted(false);
        baseDTO.setStatus(true);
        UserBaseDO userBaseDTO = userBaseService.get(baseDTO);
        if(userBaseDTO == null){
            //手机号未注册
            logger.info("登录手机号未注册，直接注册:"+loginRequestVO.getPhoto());
            baseDTO.setCreateTime(new Date());
            baseDTO.setCreateBy("admin");
            // 用户昵称，手机注册登录，默认昵称和用户名是手机号
            baseDTO.setNickName(loginRequestVO.getNickName());
            baseDTO.setUsername(loginRequestVO.getNickName()==null?loginRequestVO.getPhone():loginRequestVO.getNickName());
            baseDTO.setPhoto(loginRequestVO.getPhoto());
            baseDTO.setGuide(Boolean.FALSE);
            boolean success = userBaseService.insert(baseDTO);
            //生成邀请码
            baseDTO.setCode(saveInviteCode(baseDTO.getId()));
            if(success){
                this.createDefaultAccount(baseDTO.getId());
                this.createDefaultPoints(baseDTO.getId());
                this.createDefaultCount(baseDTO.getId());
            }else {
                throw new BusinessException("注册失败");
            }
            //初始化
            cacheDataService.initRedisCount(baseDTO.getId());
            logger.info("初始化用户计数器完成");
            return baseDTO;
        }else{
            return   userBaseDTO;
        }
    }



    /**
     * 根据手机号查找用户，没有则创建用户
     * @param phone
     * @return
     */
    private UserBaseDO userCheck(String phone) {
        UserBaseDO baseDTO = new UserBaseDO();
        baseDTO.setPhone(phone);
        baseDTO.setDeleted(false);
        baseDTO.setStatus(true);
        UserBaseDO userBaseDTO = userBaseService.get(baseDTO);
        if(userBaseDTO == null){
            //手机号未注册
            logger.info("登录手机号未注册，直接注册:"+phone);
            baseDTO.setCreateTime(new Date());
            baseDTO.setCreateBy("admin");
            // 用户昵称，手机注册登录，默认昵称和用户名是手机号
            baseDTO.setNickName(phone);
            baseDTO.setUsername(phone);
            baseDTO.setGuide(Boolean.FALSE);
            boolean success = userBaseService.insert(baseDTO);
            //生成邀请码
            baseDTO.setCode(saveInviteCode(baseDTO.getId()));
            if(success){
                this.createDefaultAccount(baseDTO.getId());
                this.createDefaultPoints(baseDTO.getId());
                this.createDefaultCount(baseDTO.getId());
            }else {
                throw new BusinessException("注册失败");
            }
             //初始化
            cacheDataService.initRedisCount(baseDTO.getId());
            logger.info("初始化用户计数器完成");
            return baseDTO;
        }else{
            return   userBaseDTO;
        }
    }

    /**
     * 生成邀请码 并保存
     * @param userId
     */
    @Override
    public String saveInviteCode(Integer userId){
        String inviteCode = ShareCodeUtil.id2ShareCode(userId);
        UserBaseDO ub = new UserBaseDO();
        ub.setId(userId);
        ub.setCode(inviteCode);
        userBaseService.updateById(ub);
        return inviteCode;
    }

    /**
     * 创建默认账户
     * @param userId
     */
    private void createDefaultAccount(Integer userId){
        AccountDO accountDTO = new AccountDO();
        accountDTO.setUserId(userId);
        accountDTO.setCreateTime(new Date());
        accountDTO.setDeleted(false);
        accountDTO.setMemberType(MemberTypeEnum.COMMON.getValue());
        accountDTO.setBeanNumber(0);
        accountService.insert(accountDTO);
    }

    /**
     * 创建默认积分
     * @param userId
     */
    private void createDefaultPoints(Integer userId){
        UserPointsDO userPointsDTO = new UserPointsDO();
        userPointsDTO.setUserId(userId);
        userPointsDTO.setDeleted(false);
        userPointsDTO.setCreateTime(new Date());
        userPointsDTO.setPoints(0f);
        //积分账户默认不可用，需要充值成为vip后 积分账户才可用
        userPointsDTO.setStatus(false);
        userPointsService.insert(userPointsDTO);
    }

    /**
     * 创建计数
     * @param userId
     */
    private void createDefaultCount(Integer userId){
        UserCountDO userCountDO = new UserCountDO();
        userCountDO.setUserId(userId);
        userCountDO.setLikeCount(0);
        userCountDO.setCollectCount(0);
        userCountDO.setTotalLearnTime(0f);
        userCountDO.setTodayLearnTime(0f);
        userCountService.insert(userCountDO);
    }


    private LoginSuccessDTO buildLoginSuccess( UserBaseDO user, String token) {
        LoginSuccessDTO successDTO =  this.buildLoginSuccess(user);
        successDTO.setToken(token);
        return successDTO;
    }



    @Override
    public LoginSuccessDTO buildLoginSuccess( UserBaseDO user) {
        LoginSuccessDTO success = BeanUtil.convert(user,LoginSuccessDTO.class);
        cacheDataService.getUserRedisCount(success);
        AccountDO query = new AccountDO();
        query.setUserId(user.getId());
        AccountDO accountDTO = accountService.get(query);
        //历史豆数
        success.setBeansCount(accountDTO.getBeanNumber());
        //会员类型
        success.setMemberType(accountDTO.getMemberType());
        //积分
        PointsRankModel rankModel = userPointsService.getRankByUserId(user.getId());
        if(rankModel != null){
            success.setPoints(rankModel.getPoints().floatValue());
            success.setRank(rankModel.getRank());
        }

        UserCountDO queryCount = new UserCountDO();
        queryCount.setUserId(user.getId());
        UserCountDO userCountDO = userCountDao.get(queryCount);
        if(userCountDO != null){
            success.setTotalLeanTime(userCountDO.getTotalLearnTime().intValue());
            success.setTodayLeanTime(userCountDO.getTodayLearnTime().intValue());
        }

        //订单数
        UserOrderDO queryOrder = new UserOrderDO();
        queryOrder.setUserId(user.getId());
//        List<UserOrderDO> orderList = userOrderService.getList(queryOrder);
        List<UserOrderDO> orderList = userOrderService.getAreadyPayOrderList(queryOrder);
        if(CollectionUtils.isEmpty(orderList)){
            success.setOrderCount(0);
        }else{
            success.setOrderCount(orderList.size());
        }


        success.setCompleteCertification(StringUtils.isEmpty(success.getGrade())?false:true);
        return success;
    }

    /**
     * 绑定手机号
     *
     * @param phone
     * @param code
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindingPhone(String phone, String code) {
        //校验验证码是否正确
        validservice.validMessageCodeThrowE(phone,code, SmsTypeEnum.BINDING_CODE.getValue());
        UserBaseDO user = ThreadUser.getUser(UserBaseDO.class);
        UserBaseDO updateDTO= new UserBaseDO();
        updateDTO.setId(user.getId());
        updateDTO.setPhone(phone);
        return userBaseService.updateById(updateDTO);
    }

    /**
     * 保存缓存
     * @param token
     * @param jsonUser
     */
    private void saveLoginCache( String token, String jsonUser) {
        String tokenRedisKey = RedisCacheConstant.KEY_APP_TOKEN +token;
        redisUtils.setString(tokenRedisKey,tokenExpire , jsonUser);
        ThreadUser.setUserJson(jsonUser);
        ThreadUser.setUserTokenRdisKey(tokenRedisKey);
    }

    /**
     * 创建token
     *
     * @return
     */
    private String createToken() {
        return MD5Util.encrypt( String.valueOf(System.currentTimeMillis()), UUIDGenerator.getUUID());

    }


}
